Skip to main content

Basic Usage

Setting Up Your Main File

main.js
const path = require("path");
const Piscina = require("piscina");

// Create a new Piscina instance pointing to your worker file
const piscina = new Piscina({
filename: path.resolve(__dirname, "worker.js"),
});

// Run a task using Piscina
(async () => {
const result = await piscina.run({ a: 4, b: 6 });
console.log(result); // prints 10
})();

Using a Worker Wrapper File in a TypeScript Project

When working with TypeScript, you need to use a workerWrapper.js file to load your worker file correctly. This file checks if the provided file path ends with .ts and registers the ts-node compiler to handle TypeScript files. You can learn more about using Typescript with Piscina in the examples section.

workerWrapper.js
const { workerData } = require('worker_threads');

if (workerData.fullpath.endsWith(".ts")) {
require("ts-node").register();
}
module.exports = require(workerData.fullpath);

Creating a Worker File

worker.js
// A simple worker function that adds two numbers
module.exports = ({ a, b }) => a + b;

Using Async Functions or Promises

Workers can be asynchronous or return a promise:

const { setTimeout } = require("timers/promises");

// An async worker function with simulated delay
module.exports = async ({ a, b }) => {
// Fake some async activity with a delay
await setTimeout(100);
return a + b;
};

Supporting ECMAScript Modules (ESM)

Piscina.js also works with ECMAScript modules:

import { Piscina } from "piscina";

const piscina = new Piscina({
// The URL must be a file:// URL
filename: new URL("./worker.mjs", import.meta.url).href,
});

const result = await piscina.run({ a: 4, b: 6 });
console.log(result); // Prints 10

In your worker module file:

worker.mjs
// Default export of an addition function
export default ({ a, b }) => a + b;

Exporting Multiple Worker Functions

A single worker file may export multiple named handler functions:

worker.js
"use strict";

function add({ a, b }) {
return a + b;
}

function multiply({ a, b }) {
return a * b;
}

add.add = add;
add.multiply = multiply;

module.exports = add;

The export to target can then be specified when the task is submitted:

main.js
"use strict";

const Piscina = require("piscina");
const { resolve } = require("path");

// Initialize Piscina with the worker file
const piscina = new Piscina({
filename: resolve(__dirname, "worker.js"),
});

// Run multiple tasks concurrently
(async () => {
const [sum, product] = await Promise.all([
piscina.run({ a: 4, b: 6 }, { name: "add" }),
piscina.run({ a: 4, b: 6 }, { name: "multiply" }),
]);
})();

Cancellable Tasks

Piscina supports task cancellation even if the task has already been submitted to a worker and is being actively processed. This can be used, for instance, to cancel tasks that are taking too long to run.

Tasks can be canceled using an AbortController or an EventEmitter.

Using AbortController

main.js
"use strict";

const Piscina = require("piscina");
const { resolve } = require("path");

// Set up Piscina with the worker file
const piscina = new Piscina({
filename: resolve(__dirname, "worker.js"),
});

// Run a task and cancel it using AbortController
(async () => {
const abortController = new AbortController();
const { signal } = abortController;
const task = piscina.run({ a: 4, b: 6 }, { signal });
abortController.abort(); // Cancel the task

try {
await task;
} catch (err) {
console.log("The task was canceled"); // Handle the cancellation
}
})();

Using EventEmitter

A plain Node.js EventEmitter can also be used here, in which case, emitting the abort event on it will have the same effect.

main.js
"use strict";

const Piscina = require("piscina");
const EventEmitter = require("events");
const { resolve } = require("path");

// Initialize Piscina with the worker file
const piscina = new Piscina({
filename: resolve(__dirname, "worker.js"),
});

// Run a task and cancel it using an EventEmitter
(async () => {
const ee = new EventEmitter();
const task = piscina.run({ a: 4, b: 6 }, { signal: ee });
ee.emit("abort"); // Emit an 'abort' event to cancel the task

try {
await task;
} catch (err) {
console.log("The task was canceled"); // Handle the cancellation
}
})();

Find more use cases in the Examples section of the documentation